using Lzfy_Refund_Service.Models;
using Lzfy_Refund_Service.Repositories;

namespace Lzfy_Refund_Service.Services
{
    public class RefundTaskMasterService : IRefundTaskMasterService
    {
        private readonly IRefundTaskMasterRepository _repository;
        private readonly IRefundTaskDetailRepository _detailRepository;
        private readonly ILogger<RefundTaskMasterService> _logger;

        public RefundTaskMasterService(
            IRefundTaskMasterRepository repository,
            IRefundTaskDetailRepository detailRepository,
            ILogger<RefundTaskMasterService> logger)
        {
            _repository = repository;
            _detailRepository = detailRepository;
            _logger = logger;
        }

        public async Task<RefundTaskMasterResponse?> GetByIdAsync(long id)
        {
            try
            {
                var master = await _repository.GetByIdAsync(id);
                if (master == null) return null;

                var details = await _detailRepository.GetByMasterIdAsync(id);
                
                return new RefundTaskMasterResponse
                {
                    Id = master.Id,
                    InputDate = master.InputDate,
                    Username = master.Username,
                    Fullname = master.Fullname,
                    AccountCount = master.AccountCount,
                    AccountSumBalance = master.AccountSumBalance,
                    Details = details.Select(d => new RefundTaskDetailResponse
                    {
                        Id = d.Id,
                        InputDate = d.InputDate,
                        MasterId = d.MasterId,
                        PatientId = d.PatientId,
                        AccountId = d.AccountId,
                        AccountIndex = d.AccountIndex,
                        Balance = d.Balance,
                        ContactCount = d.ContactCount,
                        ContactTime1 = d.ContactTime1,
                        ContactTime2 = d.ContactTime2,
                        ContactTime3 = d.ContactTime3,
                        ContactTime4 = d.ContactTime4,
                        ContactTime5 = d.ContactTime5,
                        PhoneNumber = d.PhoneNumber,
                        PatName = d.PatName,
                        IdNumber = d.IdNumber,
                        Sex = d.Sex,
                        NextOfKin = d.NextOfKin,
                        NextOfKinPhone = d.NextOfKinPhone,
                        GuardianName = d.GuardianName,
                        GuardianIdcode = d.GuardianIdcode
                    }).ToList()
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting refund task master by id: {Id}", id);
                throw;
            }
        }

        public async Task<IEnumerable<RefundTaskMasterResponse>> GetAllAsync()
        {
            try
            {
                var masters = await _repository.GetAllAsync();
                var responses = new List<RefundTaskMasterResponse>();

                foreach (var master in masters)
                {
                    var details = await _detailRepository.GetByMasterIdAsync(master.Id);
                    responses.Add(new RefundTaskMasterResponse
                    {
                        Id = master.Id,
                        InputDate = master.InputDate,
                        Username = master.Username,
                        Fullname = master.Fullname,
                        AccountCount = master.AccountCount,
                        AccountSumBalance = master.AccountSumBalance,
                        Details = details.Select(d => new RefundTaskDetailResponse
                        {
                            Id = d.Id,
                            InputDate = d.InputDate,
                            MasterId = d.MasterId,
                            PatientId = d.PatientId,
                            AccountId = d.AccountId,
                            AccountIndex = d.AccountIndex,
                            Balance = d.Balance,
                            ContactCount = d.ContactCount,
                            ContactTime1 = d.ContactTime1,
                            ContactTime2 = d.ContactTime2,
                            ContactTime3 = d.ContactTime3,
                            ContactTime4 = d.ContactTime4,
                            ContactTime5 = d.ContactTime5,
                            PhoneNumber = d.PhoneNumber,
                            PatName = d.PatName,
                            IdNumber = d.IdNumber,
                            Sex = d.Sex,
                            NextOfKin = d.NextOfKin,
                            NextOfKinPhone = d.NextOfKinPhone,
                            GuardianName = d.GuardianName,
                            GuardianIdcode = d.GuardianIdcode
                        }).ToList()
                    });
                }

                return responses;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting all refund task masters");
                throw;
            }
        }

        public async Task<(IEnumerable<RefundTaskMasterResponse> data, int totalCount)> GetWithFilterAsync(RefundTaskMasterQueryRequest request)
        {
            try
            {
                var (masters, totalCount) = await _repository.GetWithFilterAsync(
                    request.StartDate,
                    request.EndDate,
                    request.Username,
                    request.Fullname,
                    request.PageIndex,
                    request.PageSize);

                var responses = new List<RefundTaskMasterResponse>();

                foreach (var master in masters)
                {
                    var details = await _detailRepository.GetByMasterIdAsync(master.Id);
                    responses.Add(new RefundTaskMasterResponse
                    {
                        Id = master.Id,
                        InputDate = master.InputDate,
                        Username = master.Username,
                        Fullname = master.Fullname,
                        AccountCount = master.AccountCount,
                        AccountSumBalance = master.AccountSumBalance,
                        Details = details.Select(d => new RefundTaskDetailResponse
                        {
                            Id = d.Id,
                            InputDate = d.InputDate,
                            MasterId = d.MasterId,
                            PatientId = d.PatientId,
                            AccountId = d.AccountId,
                            AccountIndex = d.AccountIndex,
                            Balance = d.Balance,
                            ContactCount = d.ContactCount,
                            ContactTime1 = d.ContactTime1,
                            ContactTime2 = d.ContactTime2,
                            ContactTime3 = d.ContactTime3,
                            ContactTime4 = d.ContactTime4,
                            ContactTime5 = d.ContactTime5,
                            PhoneNumber = d.PhoneNumber,
                            PatName = d.PatName,
                            IdNumber = d.IdNumber,
                            Sex = d.Sex,
                            NextOfKin = d.NextOfKin,
                            NextOfKinPhone = d.NextOfKinPhone,
                            GuardianName = d.GuardianName,
                            GuardianIdcode = d.GuardianIdcode
                        }).ToList()
                    });
                }

                return (responses, totalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting refund task masters with filter");
                throw;
            }
        }

        public async Task<IEnumerable<RefundTaskMasterResponse>> GetByUsernameAsync(string username)
        {
            try
            {
                var masters = await _repository.GetByUsernameAsync(username);
                var responses = new List<RefundTaskMasterResponse>();

                foreach (var master in masters)
                {
                    responses.Add(new RefundTaskMasterResponse
                    {
                        Id = master.Id,
                        InputDate = master.InputDate,
                        Username = master.Username,
                        Fullname = master.Fullname,
                        AccountCount = master.AccountCount,
                        AccountSumBalance = master.AccountSumBalance,
                        Details = new List<RefundTaskDetailResponse>() // 不返回明细数据，只返回空列表
                    });
                }

                return responses;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting refund task masters by username: {Username}", username);
                throw;
            }
        }

        public async Task<long> CreateAsync(RefundTaskMasterCreateRequest request)
        {
            try
            {
                var master = new RefundTaskMaster
                {
                    Username = request.Username,
                    Fullname = request.Fullname,
                    AccountCount = request.AccountCount,
                    AccountSumBalance = request.AccountSumBalance
                };

                return await _repository.CreateAsync(master);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating refund task master");
                throw;
            }
        }

        public async Task<bool> UpdateAsync(long id, RefundTaskMasterUpdateRequest request)
        {
            try
            {
                var existing = await _repository.GetByIdAsync(id);
                if (existing == null) return false;

                existing.Username = request.Username;
                existing.Fullname = request.Fullname;
                existing.AccountCount = request.AccountCount;
                existing.AccountSumBalance = request.AccountSumBalance;

                return await _repository.UpdateAsync(existing);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating refund task master: {Id}", id);
                throw;
            }
        }

        public async Task<bool> DeleteAsync(long id)
        {
            try
            {
                // First delete all related details
                await _detailRepository.DeleteByMasterIdAsync(id);
                
                // Then delete the master
                return await _repository.DeleteAsync(id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting refund task master: {Id}", id);
                throw;
            }
        }

        public async Task<RefundTaskMasterResponse?> GetWithDetailsAsync(long id)
        {
            return await GetByIdAsync(id);
        }

        public async Task<long> CreateWithHisDataAsync(RefundTaskMasterCreateRequest request)
        {
            try
            {
                // 1. 创建主表记录
                var master = new RefundTaskMaster
                {
                    Username = request.Username,
                    Fullname = request.Fullname,
                    AccountCount = 0, // 初始为0，后续会更新
                    AccountSumBalance = 0 // 初始为0，后续会更新
                };

                var masterId = await _repository.CreateAsync(master);
                _logger.LogInformation("Created refund task master with ID: {MasterId} for user: {Username}", masterId, request.Username);

                // 2. 从HIS数据库查询明细数据
                var hisRefundData = await _detailRepository.GetHisRefundDataAsync();
                _logger.LogInformation("Retrieved {Count} HIS refund data records", hisRefundData.Count());

                if (hisRefundData.Any())
                {
                    // 3. 设置master_id并批量插入明细数据
                    var details = hisRefundData.Select(data => new RefundTaskDetail
                    {
                        MasterId = masterId,
                        PatientId = data.PatientId,
                        AccountId = data.AccountId,
                        AccountIndex = data.AccountIndex,
                        Balance = data.Balance,
                        ContactCount = 0,
                        PhoneNumber = data.PhoneNumber,
                        PatName = data.PatName,
                        IdNumber = data.IdNumber,
                        Sex = data.Sex,
                        NextOfKin = data.NextOfKin,
                        NextOfKinPhone = data.NextOfKinPhone,
                        GuardianName = data.GuardianName,
                        GuardianIdcode = data.GuardianIdcode
                    }).ToList();

                    var batchInsertSuccess = await _detailRepository.BatchCreateAsync(details);
                    if (!batchInsertSuccess)
                    {
                        _logger.LogError("Failed to batch insert refund task details for master ID: {MasterId}", masterId);
                        throw new Exception("Failed to batch insert refund task details");
                    }

                    _logger.LogInformation("Successfully batch inserted {Count} refund task details for master ID: {MasterId}", details.Count, masterId);

                    // 4. 更新主表的汇总数据
                    await _repository.UpdateBalanceFromDetailsAsync(masterId);
                    _logger.LogInformation("Updated balance summary for master ID: {MasterId}", masterId);
                }
                else
                {
                    _logger.LogWarning("No HIS refund data found for master ID: {MasterId}", masterId);
                }

                return masterId;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating refund task master with HIS data");
                throw;
            }
        }
    }
}